package com.example.chainsave.upload.controller;

import com.example.chainsave.common.exception.BizException;
import com.example.chainsave.common.model.Result;
import com.example.chainsave.fabric.model.FileMetadata;
import com.example.chainsave.upload.dto.FileUploadDTO;
import com.example.chainsave.upload.dto.FileUploadRequestDTO;
import com.example.chainsave.upload.service.FileService;
import com.example.chainsave.upload.service.SaveAndFabricService;
import com.example.chainsave.upload.util.FilePathUtil;
import com.example.chainsave.upload.util.FileUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.http.fileupload.servlet.ServletFileUpload;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileNotFoundException;
import java.util.List;

@Controller
@RequestMapping(value = "/")
@Slf4j
public class FileController {


    @Autowired
    private FileService fileService;

    @Autowired
    private HttpServletRequest request;

    @Autowired
    private HttpServletResponse response;

    @Autowired
    private SaveAndFabricService saveAndFabricService;

    @Autowired
    private FilePathUtil filePathUtil;

    @GetMapping(value = "/test")
    public String gotoFilePage() {
        return "upload";
    }

    @PostMapping(value = "/upload")
    @ResponseBody
    public Result<FileUploadDTO> upload(FileUploadRequestDTO fileUploadRequestDTO) throws Exception {

        boolean isMultipart = ServletFileUpload.isMultipartContent(request);
        FileUploadDTO fileUploadDTO = null;
        if (isMultipart) {
//            StopWatch stopWatch = new StopWatch();
//            stopWatch.start("upload");
            if (fileUploadRequestDTO.getChunk() != null && fileUploadRequestDTO.getChunks() > 0) {
                fileUploadDTO = fileService.sliceUpload(fileUploadRequestDTO);
            } else {
                fileUploadDTO = fileService.upload(fileUploadRequestDTO);
            }
//            stopWatch.stop();
//            log.info("{}", stopWatch.prettyPrint());

            return new Result<FileUploadDTO>().setData(fileUploadDTO);
        }

        throw new BizException("上传失败", 406);

    }

    @RequestMapping(value = "/checkFileMd5", method = RequestMethod.POST)
    @ResponseBody
    public Result<FileUploadDTO> checkFileMd5(FileUploadRequestDTO fileUploadRequestDTO) throws Exception {
//        System.out.println(fileUploadRequestDTO.getMd5());
        log.info("文件" + fileUploadRequestDTO.getName() + "的md5值为:" + fileUploadRequestDTO.getMd5());
        FileUploadDTO fileUploadDTO = fileService.checkFileMd5(fileUploadRequestDTO);

        return new Result<FileUploadDTO>().setData(fileUploadDTO);
    }

    @PostMapping("/download")
    @ResponseBody
    public Result<String> download(Integer fileMetadataId) {
        Result<String> result = new Result<>();
        try {
            //调用存储接口将文件下载到本地,检查文件有无被篡改，返回结果信息，如果正常则开始下载
            Result<FileMetadata> check = saveAndFabricService.download(fileMetadataId);
            result.setCode(check.getCode()).setMessage(check.getMessage());
            if (check.getCode() == 200) {
                FileMetadata fileMetadata = check.getData();
                FileUtil.downloadFile(fileMetadata.getFileName(), filePathUtil.getFilePath(fileMetadata), request, response);
            } else {
                response.setStatus(500);
                throw new BizException("文件已被篡改", 407);
            }

        } catch (FileNotFoundException e) {
            log.error("download error:" + e.getMessage(), e);
            log.error("fabric error: 查询文件元信息失败--" + e.getMessage(), e);
            throw new BizException("文件下载失败", 406);
        }
        return result;
    }

    //列出用户所有完整的文件
    @GetMapping("/listUserFile")
    @ResponseBody
    public Result<List<FileMetadata>> listUserFile() throws Exception {
        Result<List<FileMetadata>> result = saveAndFabricService.listUserFile();

        return result;
    }

    //删除文件
    @PostMapping("/deleteFile")
    @ResponseBody
    public Result<String> deleteFile(Integer fileMetadataId) throws Exception {
        Result<String> result = saveAndFabricService.deleteFile(fileMetadataId);
        return result;
    }
}
